/**
  @(#)$Id: AL_TreeNodeSeq.h 85 2013-10-17 11:37:59Z xiaoting $
  @brief	Each of the data structure corresponds to a data node storage unit, this storage unit is called storage node, the node can 
  also be referred to.

  The related concepts of tree node 
  1.degree		degree node: A node of the subtree containing the number is called the node degree;
  2.leaf			leaf nodes or terminal nodes: degree 0 are called leaf nodes;
  3.branch		non-terminal node or branch node: node degree is not 0;
  4.parent		parent node or the parent node: If a node contains a child node, this node is called its child node's parent;
  5.child			child node or child node: A node subtree containing the root node is called the node's children;
  6.slibing		sibling nodes: nodes with the same parent node is called mutual sibling;
  7.ancestor		ancestor node: from the root to the node through all the nodes on the branch;
  8.descendant	descendant nodes: a node in the subtree rooted at any node is called the node's descendants.

  ////////////////////////////////Sequential storage structure//////////////////////////////////////////
  Using a set of addresses in the computer storage unit sequentially stores continuous linear form of individual data elements, called 
  the linear order of the table storage structure.

  Sequential storage structure is a type of a storage structure, the structure is the logically adjacent nodes stored in the physical 
  location of the adjacent memory cells, the logical relationship between nodes from the storage unit to reflect the adjacency. 
  Storage structure thus obtained is stored in order structure, usually by means of sequential storage structure computer programming 
  language (e.g., c / c) of the array to describe.

  The main advantage of the storage structure in order to save storage space, because the allocation to the data storage unit storing 
  all nodes with data (without regard to c / c language in the array size required for the case), the logical relationship between 
  the nodes does not take additional storage space. In this method, the node can be realized on a random access, that is, each node 
  corresponds to a number, the number can be calculated directly from the node out of the memory address. However, the main 
  disadvantage of sequential storage method is easy to modify the node insert, delete operations, may have to move a series of nodes.
          
  Benefits:
	Random Access table elements. 
  Disadvantages: 
    insert and delete operations need to move elements.

  @Author $Author: xiaoting $
  @Date $Date: 2013-10-17 19:37:59 +0800 (周四, 17 十月 2013) $
  @Revision $Revision: 85 $
  @URL $URL: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeSeq.h $
  @Header $Header: https://svn.code.sf.net/p/xiaoting/game/trunk/MyProject/AL_DataStructure/groupinc/AL_TreeNodeSeq.h 85 2013-10-17 11:37:59Z xiaoting $
 */

#ifndef CXX_AL_TREENODESEQ_H
#define CXX_AL_TREENODESEQ_H

#ifndef CXX_AL_LISTSEQ_H
#include "AL_ListSeq.h"
#endif

#ifndef CXX_AL_QUEUESEQ_H
#include "AL_QueueSeq.h"
#endif


///////////////////////////////////////////////////////////////////////////
//			AL_TreeNodeSeq
///////////////////////////////////////////////////////////////////////////

template<typename T> class AL_TreeSeq;

template<typename T> 
class AL_TreeNodeSeq
{
friend class AL_TreeSeq<T>;

public:
	/**
	* Destruction
	*
	* @param
	* @return
	* @note
	* @attention 
	*/
	~AL_TreeNodeSeq();
	
	/**
	* GetLevel
	*
	* @param
	* @return	DWORD
	* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;	
	* @attention 
	*/
	DWORD GetLevel() const;

	/**
	* SetLevel
	*
	* @param	DWORD dwLevel <IN>
	* @return	
	* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;	
	* @attention 
	*/
	VOID SetLevel(DWORD dwLevel);

	/**
	* GetData
	*
	* @param
	* @return	T
	* @note 
	* @attention 
	*/
	T GetData() const;

	/**
	* SetData
	*
	* @param	const T& tData <IN>
	* @return	
	* @note 
	* @attention 
	*/
	VOID SetData(const T& tData);

	/**
	* GetParent
	*
	* @param	
	* @return	AL_TreeNodeSeq<T>*	
	* @note parent node pointer, not to manager memory
	* @attention 
	*/
	AL_TreeNodeSeq<T>*	GetParent() const;

	/**
	* SetParent
	*
	* @param	DWORD dwIndex <IN>
	* @param	AL_TreeNodeSeq<T>* pParent <IN>
	* @return	BOOL
	* @note parent node pointer, not to manager memory
	* @attention as the child to set the parent at the index (from the left of parent's child )
	*/
	BOOL SetParent(DWORD dwIndex, AL_TreeNodeSeq<T>* pParent);

	/**
	* SetParentLeft
	*
	* @param	AL_TreeNodeSeq<T>* pParent <IN>
	* @return	BOOL
	* @note parent node pointer, not to manager memory
	* @attention as the child to set the parent at the left (from the left of parent's child )
	*/
	BOOL SetParentLeft(AL_TreeNodeSeq<T>* pParent);

	/**
	* SetParentRight
	*
	* @param	AL_TreeNodeSeq<T>* pParent <IN>
	* @return	BOOL
	* @note parent node pointer, not to manager memory
	* @attention as the child to set the parent at the right (from the right of parent's child )
	*/
	BOOL SetParentRight(AL_TreeNodeSeq<T>* pParent);

	/**
	* Insert
	*
	* @param	DWORD dwIndex <IN>
	* @param	AL_TreeNodeSeq<T>* pInsertChild <IN> 
	* @return	BOOL
	* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the position
	* @attention
	*/
	BOOL Insert(DWORD dwIndex, AL_TreeNodeSeq<T>* pInsertChild);

	/**
	* InsertLeft
	*
	* @param	AL_TreeNodeSeq<T>* pInsertChild <IN> 
	* @return	BOOL
	* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the left
	* @attention
	*/
	BOOL InsertLeft(AL_TreeNodeSeq<T>* pInsertChild);

	/**
	* InsertRight
	*
	* @param	AL_TreeNodeSeq<T>* pInsertChild <IN> 
	* @return	BOOL
	* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the right
	* @attention
	*/
	BOOL InsertRight(AL_TreeNodeSeq<T>* pInsertChild);
	
	/**
	* RemoveParent
	*
	* @param
	* @return	BOOL
	* @note remove the parent note
	* @attention
	*/
	BOOL RemoveParent();

	/**
	* Remove
	*
	* @param	AL_TreeNodeSeq<T>* pRemoveChild <IN>
	* @return	BOOL
	* @note remove the notes in the child
	* @attention
	*/
	BOOL Remove(AL_TreeNodeSeq<T>* pRemoveChild);

	/**
	* Remove
	*
	* @param	DWORD dwIndex <IN>
	* @return	BOOL
	* @note remove the child notes at the position
	* @attention
	*/
	BOOL Remove(DWORD dwIndex);

	/**
	* RemoveLeft
	*
	* @param
	* @return	BOOL
	* @note remove the child notes at the left
	* @attention
	*/
	BOOL RemoveLeft();

	/**
	* RemoveRight
	*
	* @param
	* @return	BOOL
	* @note remove the child notes at the right
	* @attention
	*/
	BOOL RemoveRight();

	/**
	* GetChild
	*
	* @param	DWORD dwIndex <IN>
	* @return	AL_TreeNodeSeq<T>*
	* @note the dwIndex must is little than the node degree
	* @attention
	*/
	AL_TreeNodeSeq<T>* GetChild(DWORD dwIndex) const;

	/**
	* GetChildLeft
	*
	* @param	
	* @return	AL_TreeNodeSeq<T>*
	* @note 
	* @attention
	*/
	AL_TreeNodeSeq<T>* GetChildLeft() const;

	/**
	* GetChildRight
	*
	* @param	
	* @return	AL_TreeNodeSeq<T>*
	* @note 
	* @attention
	*/
	AL_TreeNodeSeq<T>* GetChildRight() const;
	
	/**
	* GetDegree
	*
	* @param
	* @return	DWORD
	* @note degree node: A node of the subtree containing the number is called the node degree;
	* @attention 
	*/
	DWORD GetDegree() const;

	/**
	* IsLeaf
	*
	* @param
	* @return	BOOL
	* @note leaf nodes or terminal nodes: degree 0 are called leaf nodes;
	* @attention 
	*/
	BOOL IsLeaf() const;

	/**
	* IsBranch
	*
	* @param
	* @return	BOOL
	* @note non-terminal node or branch node: node degree is not 0;
	* @attention 
	*/
	BOOL IsBranch() const;

	/**
	* IsParent
	*
	* @param	const AL_TreeNodeSeq<T>* pChild <IN>
	* @return	BOOL
	* @note parent node or the parent node: If a node contains a child node, this node is called its child 
	* @attention 
	*/
	BOOL IsParent(const AL_TreeNodeSeq<T>* pChild) const;

	/**
	* GetSibling
	*
	* @param	AL_ListSeq<AL_TreeNodeSeq<T>*>& listSibling <OUT>
	* @return	BOOL
	* @note sibling nodes: nodes with the same parent node is called mutual sibling;
	* @attention 
	*/
	BOOL GetSibling(AL_ListSeq<AL_TreeNodeSeq<T>*>& listSibling) const;

	/**
	* GetAncestor
	*
	* @param	AL_ListSeq<AL_TreeNodeSeq<T>*>& listAncestor <OUT>
	* @return	BOOL
	* @note ancestor node: from the root to the node through all the nodes on the branch;
	* @attention 
	*/
	BOOL GetAncestor(AL_ListSeq<AL_TreeNodeSeq<T>*>& listAncestor) const;

	/**
	* GetDescendant
	*
	* @param	AL_ListSeq<AL_TreeNodeSeq<T>*>& listDescendant <OUT>
	* @return	BOOL
	* @note ancestor node: from the root to the node through all the nodes on the branch;
	* @attention 
	*/
	BOOL GetDescendant(AL_ListSeq<AL_TreeNodeSeq<T>*>& listDescendant) const;

	/**
	* Clear
	*
	* @param
	* @return	VOID
	* @note
	* @attention 
	*/
	VOID Clear();

protected:
private:

	/**
	* Construction
	*
	* @param
	* @return
	* @note private the Construction, avoid the others use it
	* @attention
	*/
	AL_TreeNodeSeq();
	
	/**
	* Construction
	*
	* @param	const T& tData <IN>
	* @return
	* @note
	* @attention private the Construction, avoid the others use it
	*/
	AL_TreeNodeSeq(const T& tData);

	/**
	*Copy Construct
	*
	* @param	const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq
	* @return
	*/
	AL_TreeNodeSeq(const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq);

	/**
	*Assignment
	*
	* @param	const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq
	* @return	AL_TreeNodeSeq<T>&
	*/
	AL_TreeNodeSeq<T>& operator = (const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq);

public:
protected:
private:
	DWORD								m_dwLevel;				//Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;	
	T									m_tData;					//the friend class can use it directly

	AL_TreeNodeSeq<T>*					m_pParent;				//Parent position
	AL_ListSeq<AL_TreeNodeSeq<T>*>		m_listChild;			//All Child tree node
};

///////////////////////////////////////////////////////////////////////////
//			AL_TreeNodeSeq
///////////////////////////////////////////////////////////////////////////

/**
* Construction
*
* @param
* @return
* @note private the Construction, avoid the others use it
* @attention
*/
template<typename T>
AL_TreeNodeSeq<T>::AL_TreeNodeSeq():
m_dwLevel(0x00),
m_pParent(NULL)
{
	m_listChild.Clear();
}

/**
* Construction
*
* @param	const T& tData <IN>
* @return
* @note
* @attention private the Construction, avoid the others use it
*/
template<typename T>
AL_TreeNodeSeq<T>::AL_TreeNodeSeq(const T& tData):
m_dwLevel(0x00),
m_tData(tData),
m_pParent(NULL)
{
	m_listChild.Clear();
}


/**
* Destruction
*
* @param
* @return
* @note
* @attention 
*/
template<typename T>
AL_TreeNodeSeq<T>::~AL_TreeNodeSeq()
{
	//it doesn't matter to clear the pointer or not.
	Clear();
}

/**
* GetLevel
*
* @param
* @return	DWORD
* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;	
* @attention 
*/
template<typename T> DWORD 
AL_TreeNodeSeq<T>::GetLevel() const
{
	return m_dwLevel;
}

/**
* SetLevel
*
* @param	DWORD dwLevel <IN>
* @return	
* @note Node levels: starting from the root to start defining the root of the first layer, the root node is a sub-layer 2, and so on;	
* @attention 
*/
template<typename T> VOID 
AL_TreeNodeSeq<T>::SetLevel(DWORD dwLevel)
{
	m_dwLevel = dwLevel;
}

/**
* GetData
*
* @param
* @return	T
* @note 
* @attention 
*/
template<typename T> T 
AL_TreeNodeSeq<T>::GetData() const
{
	return m_tData;
}

/**
* SetData
*
* @param	const T& tData <IN>
* @return	
* @note 
* @attention 
*/
template<typename T> VOID 
AL_TreeNodeSeq<T>::SetData(const T& tData)
{
	m_tData = tData;
}

/**
* GetParent
*
* @param	
* @return	AL_TreeNodeSeq<T>*	
* @note parent node pointer, not to manager memory
* @attention 
*/
template<typename T> AL_TreeNodeSeq<T>* 
AL_TreeNodeSeq<T>::GetParent() const
{
	return m_pParent;
}

/**
* SetParent
*
* @param	DWORD dwIndex <IN>
* @param	AL_TreeNodeSeq<T>* pParent <IN>
* @return	BOOL
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the index (from the left of parent's child )
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::SetParent(DWORD dwIndex, AL_TreeNodeSeq<T>* pParent)
{
	if (NULL == pParent) {
		return FALSE;
	}

	BOOL  bSetParent = FALSE;
	bSetParent = pParent->Insert(dwIndex, this);
	if (TRUE == bSetParent) {
		//current node insert to the parent successfully
		if (NULL != m_pParent) {
			//current node has parent
			if (FALSE == m_pParent->Remove(this)) {
				return FALSE;
			}
		}
		m_pParent = pParent;
	}
	return bSetParent;
}

/**
* SetParentLeft
*
* @param	AL_TreeNodeSeq<T>* pParent <IN>
* @return	
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the left (from the left of parent's child )
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::SetParentLeft(AL_TreeNodeSeq<T>* pParent)
{
	return SetParent(0x00, pParent);
}

/**
* SetParentRight
*
* @param	AL_TreeNodeSeq<T>* pParent <IN>
* @return	
* @note parent node pointer, not to manager memory
* @attention as the child to set the parent at the right (from the right of parent's child )
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::SetParentRight(AL_TreeNodeSeq<T>* pParent)
{
	if (NULL == pParent) {
		return FALSE;
	}

	return SetParent(pParent->GetDegree(), pParent);
}

/**
* Insert
*
* @param	DWORD dwIndex <IN>
* @param	AL_TreeNodeSeq<T>* pInsertChild <IN> 
* @return	BOOL
* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the position
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::Insert(DWORD dwIndex, AL_TreeNodeSeq<T>* pInsertChild)
{
	if (GetDegree() < dwIndex || NULL == pInsertChild) {
		return FALSE;
	}
	
	if (this == pInsertChild) {
		//itself
		return FALSE;
	}

	BOOL  bInsert = FALSE;
	bInsert = m_listChild.Insert(dwIndex, pInsertChild);
	if (TRUE == bInsert) {
		if (GetLevel()+1 != pInsertChild->GetLevel()) {
			//deal with the child level
			INT iLevelDiff = pInsertChild->GetLevel() - GetLevel();

			AL_ListSeq<AL_TreeNodeSeq<T>*> listDescendant;
			if (TRUE == GetDescendant(listDescendant)) {
				//insert child node has descendant
				AL_TreeNodeSeq<T>* pDescendant = NULL;
				for (DWORD dwCnt=0x00; dwCnt<listDescendant.Length(); dwCnt++) {
					if (TRUE == listDescendant.Get(dwCnt, pDescendant)) {
						if (NULL != pDescendant) {
							//set child level
							pDescendant->SetLevel(pDescendant->GetLevel()-iLevelDiff+1);
						}
						else {
							//error
							return FALSE;
						}
					}
					else {
						//error
						return FALSE;
					}
				}
			}
		}
		//child node insert to the current successfully
		pInsertChild->m_pParent = this;
	}
	return bInsert;
}

/**
* InsertLeft
*
* @param	AL_TreeNodeSeq<T>* pInsertChild <IN> 
* @return	BOOL
* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the left
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::InsertLeft(AL_TreeNodeSeq<T>* pInsertChild)
{
	return Insert(0x00, pInsertChild);
}

/**
* InsertRight
*
* @param	AL_TreeNodeSeq<T>* pInsertChild <IN> 
* @return	BOOL
* @note inset the const AL_TreeNodeSeq<T>*  into the child notes at the right
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::InsertRight(AL_TreeNodeSeq<T>* pInsertChild)
{
	return Insert(GetDegree(), pInsertChild);
}

/**
* RemoveParent
*
* @param
* @return	BOOL
* @note remove the parent note
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::RemoveParent()
{
	BOOL bRemove = FALSE;
	//don't care the parent node exist or not
	m_pParent = NULL;
	bRemove = TRUE;
	/*
	if (NULL != m_pParent) {
		m_pParent = NULL;
		bRemove = TRUE;
	}
	*/
	return bRemove;
}

/**
* Remove
*
* @param	AL_TreeNodeSeq<T>* pRemoveChild <IN>
* @return	BOOL
* @note remove the notes in the child
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::Remove(AL_TreeNodeSeq<T>* pRemoveChild)
{
	return m_listChild.Remove(pRemoveChild);
}

/**
* Remove
*
* @param	DWORD dwIndex <IN>
* @return	BOOL
* @note remove the child notes at the position
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::Remove(DWORD dwIndex)
{
	AL_TreeNodeSeq<T>* pRemoveChild = NULL;
	if (FALSE == m_listChild.Get(pRemoveChild, dwIndex)) {
		return FALSE;
	}

	return Remove(pRemoveChild);
}

/**
* RemoveLeft
*
* @param
* @return	BOOL
* @note remove the child notes at the left
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::RemoveLeft()
{
	AL_TreeNodeSeq<T>* pRemoveChild = NULL;
	if (FALSE == m_listChild.Get(pRemoveChild, 0x00)) {
		return FALSE;
	}

	return Remove(pRemoveChild);
}

/**
* RemoveRight
*
* @param
* @return	BOOL
* @note remove the child notes at the right
* @attention
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::RemoveRight()
{
	AL_TreeNodeSeq<T>* pRemoveChild = NULL;
	if (FALSE == m_listChild.Get(pRemoveChild, GetDegree())) {
		return FALSE;
	}

	return Remove(pRemoveChild);
}

/**
* GetChild
*
* @param	DWORD dwIndex <IN>
* @return	AL_TreeNodeSeq<T>*
* @note the dwIndex must is little than the node degree
* @attention
*/
template<typename T> AL_TreeNodeSeq<T>* 
AL_TreeNodeSeq<T>::GetChild(DWORD dwIndex) const
{
	AL_TreeNodeSeq<T>* pChild = NULL;
	if (TRUE == m_listChild.Get(dwIndex, pChild)) {
		return pChild;
	}
	return NULL;
}

/**
* GetChildLeft
*
* @param	
* @return	AL_TreeNodeSeq<T>*
* @note 
* @attention
*/
template<typename T> AL_TreeNodeSeq<T>* 
AL_TreeNodeSeq<T>::GetChildLeft() const
{
	return GetChild(0x00);
}

/**
* GetChildRight
*
* @param	
* @return	AL_TreeNodeSeq<T>*
* @note 
* @attention
*/
template<typename T> AL_TreeNodeSeq<T>* 
AL_TreeNodeSeq<T>::GetChildRight() const
{
	return GetChild(GetDegree());
}

/**
* GetDegree
*
* @param
* @return	DWORD
* @note degree node: A node of the subtree containing the number is called the node degree;
* @attention 
*/
template<typename T> DWORD 
AL_TreeNodeSeq<T>::GetDegree() const
{
	return m_listChild.Length();
}

/**
* IsLeaf
*
* @param
* @return	BOOL
* @note leaf nodes or terminal nodes: degree 0 are called leaf nodes;
* @attention 
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::IsLeaf() const
{
	return (0x00 == GetDegree()) ? TRUE:FALSE;
}

/**
* IsBranch
*
* @param
* @return	BOOL
* @note non-terminal node or branch node: node degree is not 0;
* @attention 
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::IsBranch() const
{
	return (0x00 != GetDegree()) ? TRUE:FALSE;
}

/**
* IsParent
*
* @param	const AL_TreeNodeSeq<T>* pChild <IN>
* @return	BOOL
* @note parent node or the parent node: If a node contains a child node, this node is called its child 
* @attention 
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::IsParent(const AL_TreeNodeSeq<T>* pChild) const
{
	if (NULL ==  pChild) {
		return FALSE;
	}
	// 	AL_TreeNodeSeq<T>* pCompare = NULL;
	// 	for (DWORD dwCnt=0x00; dwCnt<GetDegree(); dwCnt++) {
	// 		if (TRUE == m_listChild.Get(pCompare, dwCnt)) {
	// 			if (pCompare == pChild) {
	// 				//find the child
	// 				return TRUE;
	// 			}
	// 		}
	// 	}
	// 	return FALSE;

	if (this == pChild->m_pParent) {
		return TRUE;
	}
	return FALSE;
}

/**
* GetSibling
*
* @param	AL_ListSeq<AL_TreeNodeSeq<T>*>& listSibling <OUT>
* @return	BOOL
* @note sibling nodes: nodes with the same parent node is called mutual sibling;
* @attention 
*/
template<typename T> BOOL
AL_TreeNodeSeq<T>::GetSibling(AL_ListSeq<AL_TreeNodeSeq<T>*>& listSibling) const
{
	BOOL bSibling = FALSE;
	if (NULL == m_pParent) {
		//not parent node
		return bSibling;
	}

	listSibling.Clear();
	AL_TreeNodeSeq<T>* pParentChild = NULL;
	for (DWORD dwCnt=0x00; dwCnt<m_pParent->GetDegree(); dwCnt++) {
		pParentChild = m_pParent->GetChild(dwCnt);
		if (NULL != pParentChild) {
			//get the child
			if (pParentChild == this) {
				//itself
				continue;
			}
			listSibling.InsertEnd(pParentChild);
			bSibling = TRUE;
		}
		else {
			//error can not get the child
			return FALSE;
		}
	}
	return bSibling;
}

/**
* GetAncestor
*
* @param	AL_ListSeq<AL_TreeNodeSeq<T>*>& listAncestor <OUT>
* @return	BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention 
*/
template<typename T> BOOL
AL_TreeNodeSeq<T>::GetAncestor(AL_ListSeq<AL_TreeNodeSeq<T>*>& listAncestor) const
{
	if (NULL == m_pParent) {
		//not parent node
		return FALSE;
	}

	listAncestor.Clear();
	AL_TreeNodeSeq<T>* pParent = m_pParent;
	while (NULL != pParent) {
		listAncestor.InsertEnd(pParent);
		pParent = pParent->m_pParent;
	}
	return TRUE;
}

/**
* GetDescendant
*
* @param	AL_ListSeq<AL_TreeNodeSeq<T>*>& listDescendant <OUT>
* @return	BOOL
* @note ancestor node: from the root to the node through all the nodes on the branch;
* @attention 
*/
template<typename T> BOOL 
AL_TreeNodeSeq<T>::GetDescendant(AL_ListSeq<AL_TreeNodeSeq<T>*>& listDescendant) const
{
	if (TRUE == IsLeaf()) {
		//child node
		return FALSE;
	}
	
	listDescendant.Clear();
	AL_TreeNodeSeq<T>* pDescendant = NULL;
	for (DWORD dwCnt=0x00; dwCnt<GetDegree(); dwCnt++) {
		pDescendant = GetChild(dwCnt);
		if (NULL != pDescendant) {
			//get the child
			listDescendant.InsertEnd(pDescendant);
		}
		else {
			//error can not get the child
			return FALSE;
		}
	}

	//loop the all node in listDescendant
	DWORD dwDescendantLoop = 0x00;
	AL_TreeNodeSeq<T>* pDescendantLoop = NULL;
	while (TRUE == listDescendant.Get(dwDescendantLoop, pDescendant)) {
		dwDescendantLoop++;
		if (NULL != pDescendant) {
			for (DWORD dwCnt=0x00; dwCnt<pDescendant->GetDegree(); dwCnt++) {
				pDescendantLoop = pDescendant->GetChild(dwCnt);
				if (NULL != pDescendantLoop) {
					//get the descendant
					listDescendant.InsertEnd(pDescendantLoop);
				}
				else {
					//error can not get the descendant
					return FALSE;
				}
			}
		}
		else {
			//error
			return FALSE;
		}
	}
	return TRUE;
	/*
	AL_TreeNodeSeq<T>* pDescendant = NULL;
	AL_QueueSeq<AL_TreeNodeSeq<T>*> queueDescendant;
	for (DWORD dwCnt=0x00; dwCnt<GetDegree(); dwCnt++) {
		pDescendant = GetChild(dwCnt);
		if (NULL != pDescendant) {
			//get the child
			queueDescendant.Push(pDescendant);
		}
		else {
			//error can not get the child
			return FALSE;
		}
	}
	AL_TreeNodeSeq<T>* pDescendantLoop = NULL;
	AL_TreeNodeSeq<T>* pDescendantChild = NULL;
	while (FALSE == queueDescendant.IsEmpty()) {
		if (TRUE == queueDescendant.Pop(pDescendantLoop)) {
			if (NULL != pDescendantLoop) {
				listDescendant.InsertEnd(pDescendantLoop); 
				for (DWORD dwCnt=0x00; dwCnt<pDescendantLoop->GetDegree(); dwCnt++) {
					pDescendantChild = pDescendantLoop->GetChild(dwCnt);
					if (NULL != pDescendantChild) {
						queueDescendant.Push(pDescendantChild);
					}
				}
			}
			else {
				return FALSE;
			}
		}
		else {
			return FALSE;
		}
	}
	return TRUE;
	*/
}

/**
* Clear
*
* @param
* @return	VOID
* @note
* @attention 
*/
template<typename T> VOID 
AL_TreeNodeSeq<T>::Clear()
{
	m_dwLevel = 0x00;
	m_pParent = NULL;
	m_listChild.Clear();
}

/**
*Assignment
*
* @param	const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq
* @return	AL_TreeNodeSeq<T>&
*/
template<typename T> AL_TreeNodeSeq<T>& 
AL_TreeNodeSeq<T>::operator = (const AL_TreeNodeSeq<T>& cAL_TreeNodeSeq)
{
	m_dwLevel = cAL_TreeNodeSeq.m_dwLevel;
	m_tData = cAL_TreeNodeSeq.m_tData;
	m_pParent = cAL_TreeNodeSeq.m_pParent;
	m_listChild = cAL_TreeNodeSeq.m_listChild;
	return *this;
}
#endif // CXX_AL_TREENODESEQ_H
/* EOF */
